import React, { useState, useImperativeHandle, useMemo } from "react";
import { Table } from "antd";
import QueryBar from "../query-bar/QueryBar";
import styled from "styled-components";
import useGetState from "@/hooks/useGetState";
import useMyContext from "@/hooks/useContext";
import { utils, writeFile } from "xlsx";
const Styled = styled.div``;

const CrudTable = (props, ref) => {
  //组件接收的数据
  /* 
      是否不设定列的分割线 
      true: 后端分页 false: 前端分页 
      是否分页
      表格内容的横向宽度
      主键 name
      需要展示的列
      是否需要边框
      queryBar 中的参数
      补充参数（可选）
      获取文章列表数据，参数如下
          * ! 约定接口入参出参
          * * 分页模式需约定分页接口入参
          *    @param {number} pageSize 分页参数: 一页展示多少条，默认 10
          *    @param {number} pageNum  分页参数: 页码，默认 1
          * * 需约定接口出参
          *    @param {number} pageData 分页模式必须, 非分页模式如果没有 pageData 则取上一层 data
          *    @param {number} total    分页模式必须，非分页模式如果没有 total 则取上一层 data.length
  */
  const {
    singleLine = false,
    remote = true,
    isPagination = true,
    scrollX = 1200,
    rowKey = "id",
    columns = [],
    bordered = true,
    getQueryItems,
    hasRowSelection = true, //是否开启全选列
    queryItems = function () {
      console.log("默认函数queryItems");
      return {};
    },

    getExtraparams = function () {
      console.log("默认函数extraParams");
      return {};
    },
    getData,
    updateQueryItems = function () {
      console.log("updateQueryItems");
    },
    setTableSelections = function () {
      console.log("setTableSelections");
    },
  } = props;

  const [dataSource, setDataSource] = useState([]);

  //表格第一列多选
  const [selectionType, setSelectionType, getSelectionType] =
    useGetState("checkbox");

  //分页器配置
  const [pagination, setPagination, getPagination] = useGetState({
    page: 1,
    pageSize: 10,
    showSizeChanger: true,
    pageSizeOptions: [5, 10, 20],
    total: 0,
    showTotal: (total) => `共 ${total} 条`,
  });

  //表格loading
  const [loading, setLoading, getLoading] = useGetState(false);
  const { messageApi } = useMyContext();

  // 处理插槽逻辑
  const children = React.Children.toArray(props.children);
  let queryBarSlot = [];
  children.forEach((item) => {
    let slot = item.props?.slot;
    if (slot === "queryBar") queryBarSlot.push(item);
  });

  //搜索区域
  function handleSearch() {
    let params = {
      ...pagination,
      page: 1,
    };
    //确保别的地方获取的paginationRef值是最新的，然后更新视图
    setPagination(params);
    handleQuery();
  }
  //重置
  function handleReset() {
    const new_queryItems = { ...queryItems };
    for (const key in new_queryItems) {
      //将queryBar中的搜索组件内容全部清空
      Reflect.has(new_queryItems, key) &&
        Reflect.deleteProperty(new_queryItems, key);
    }
    updateQueryItems(new_queryItems);
    //页码恢复1，重新请求表单数据
    const params = {
      ...pagination,
      page: 1,
    };
    setPagination(params);
    handleQuery();
  }

  //查询函数
  async function handleQuery() {
    setSelectionType([]);
    try {
      setLoading(true);

      //使用定时器确保获取的分页数据都是最新的
      let paginationParams = {};
      const paginationRef = getPagination();
      // 如果非分页模式或者使用前端分页, 则无需传分页参数
      if (isPagination && remote) {
        paginationParams = {
          page_num: paginationRef.page,
          page_size: paginationRef.pageSize,
        };
      }
      const extraParams = getExtraparams(); //获取额外参数值
      const queryItems = getQueryItems();
      let { data } = await getData({
        ...queryItems,
        ...extraParams,
        ...paginationParams,
      });
      //设置表格数据
      setDataSource(data?.pageData || data);
      // 设置分页总数，total>0分页自动显示
      setPagination({
        ...paginationRef,
        total: data?.total,
      });
    } catch (error) {
      //设置表格数据
      setDataSource([]);
      // 设置分页总数，total>0分页自动显示
      setPagination({
        ...pagination,
        total: 0,
      });
    } finally {
      setLoading(false);
    }
  }

  //导出表格数据
  /**
   *
   * @param {*} new_columns 默认为表格的列头
   * @param {*} data 默认为表格数据
   */
  function handleExport(new_columns = columns, data = dataSource) {
    //应该是拿选中的列表和全部数据进行进行筛选
    if (data?.length === 0) {
      messageApi.warning("没有数据");
      return;
    }
    const columnsData = new_columns.filter((item) => {
      return !!item.title && !item.hideInExcel;
    });

    const thKeys = columnsData.map((item) => item.key);
    const thData = columnsData.map((item) => item.title); //列columns的标题
    const trData = data.map((item) => thKeys.map((key) => item[key])); //每列对应的数据项，每一行数组项是一行数据组成的数组
    const sheet = utils.aoa_to_sheet([thData, ...trData]);
    const workBook = utils.book_new();
    utils.book_append_sheet(workBook, sheet, "数据报表");
    writeFile(workBook, "数据报表.xlsx");
  }

  //向外暴露方法
  useImperativeHandle(
    ref,
    () => {
      return {
        //dataSource初始时候导出，后续表格更新，外部用到数据位初始空数组，因此需要依赖该项改变重新导出
        dataSource,
        handleSearch,
        handleExport,
      };
    },
    [dataSource]
  );

  return (
    <Styled>
      {queryBarSlot.length > 0 ? (
        <QueryBar handleSearch={handleSearch} handleReset={handleReset}>
          <div className="queryBar-slot " slot="queryBar">
            {queryBarSlot}
          </div>
        </QueryBar>
      ) : null}

      {/* 表格组件 */}
      <Table
        bordered={!singleLine}
        loading={loading}
        rowKey={(record) => record.id}
        rowSelection={
          hasRowSelection
            ? {
                type: selectionType,
                onChange: (selectedRowKeys, selectedRows) => {
                  const selections = selectedRows.map((item) => item.id);
                  setTableSelections(selections);
                },
              }
            : null
        }
        style={{ marginTop: "15px" }}
        columns={columns}
        dataSource={dataSource}
        pagination={{
          total: pagination.total,
          showTotal: pagination.showTotal,
          defaultPageSize: pagination.pageSize,
          defaultCurrent: pagination.page,
          current: pagination.page,
          pageSize: pagination.pageSize,
          pageSizeOptions: pagination.pageSizeOptions,
          onChange(page, pageSize) {
            setPagination({
              ...pagination,
              page,
              pageSize,
            });

            handleQuery();
          },
        }}
      />
    </Styled>
  );
};

export default React.forwardRef(CrudTable);
